# -*- coding: utf-8 -*-
import scrapy

import re
import json
import logging
import urllib.parse
from copy import copy, deepcopy
from FDC_spider.items import FdcEstateGuidItem, FdcBuildingItem, FdcRoomItem

logger = logging.getLogger(__name__)


class NanchongSpider(scrapy.Spider):
    name = 'nanchong'
    allowed_domains = ['fdcglj.nanchong.gov.cn']
    start_urls = ['http://fdcglj.nanchong.gov.cn/projectQuery/search.jspx']
    project_li_url_temp = 'http://fdcglj.nanchong.gov.cn/projectQuery/search.jspx?page={}&regionCode=&proName=&address=&licenseId=&orgName='  # GET 项目列表url
    bd_li_url = 'http://fdcglj.nanchong.gov.cn/projectQuery/getBuildings.jspx'  # POST 楼栋列表url
    rm_li_url = 'http://fdcglj.nanchong.gov.cn/projectQuery/getHouResource.jspx'  # POST 房号列表url

    def parse(self, response):
        """
        获取项目列表
        :param response:
        :return:
        """
        try:
            total_page_str = response.xpath("//a[contains(text(),'尾')]/@onclick").extract_first()
            total_page_num = self._get_total_page_num(total_page_str)
            assert isinstance(total_page_num, int) and total_page_num > 0
            page_num = int(response.xpath("//option[@selected='selected']/text()").extract_first())
        except:
            logger.error('total_page_num、page_num 获取出错')
        else:
            # 获取当前页项目列表分组
            tr_li = response.xpath("//table[contains(@class,'tab-list')]//tr")
            if len(tr_li) > 1:
                for tr in tr_li[1:]:  # 首行为标题栏
                    item_eg = FdcEstateGuidItem()
                    item_eg['preSalePermit'] = tr.xpath("./td[1]/text()").extract_first()
                    item_eg['projectName'] = tr.xpath("./td[2]/text()").extract_first()
                    item_eg['projectAddress'] = tr.xpath("./td[3]/text()").extract_first()
                    item_eg['developerName'] = tr.xpath("./td[4]/text()").extract_first()
                    item_eg['permitTotalRoomNum'] = tr.xpath("./td[5]/text()").extract_first()
                    try:
                        building_url = tr.xpath("./td[7]/a/@href").extract_first()
                        item_eg['preSaleBlockName'] = building_url.split('=')[-1]
                        regi_id = self._get_regi_id(building_url)
                        permit_url = tr.xpath("./td[6]/a/@href").extract_first()
                        assert regi_id and permit_url
                    except:
                        logger.error('{}  {} 预售楼栋名称、许可证详情url提取出错'.format(response.request.url, item_eg['projectName']))
                    else:
                        item_eg['projectId'] = regi_id

                        # 获取许可证详情
                        yield response.follow(
                            permit_url,
                            callback=self.parse_permit,
                            meta=dict(item_eg=deepcopy(item_eg), ),
                            priority=5,
                        )

                        # 获取楼栋列表
                        headers = dict(Referer=urllib.parse.urljoin(response.request.url, building_url), )
                        data = dict(regiId=regi_id, )
                        yield scrapy.FormRequest(
                            self.bd_li_url,
                            formdata=data,
                            headers=headers,
                            callback=self.parse_building_li,
                            meta=dict(item_eg=deepcopy(item_eg), building_url=building_url, ),
                            priority=5,
                        )
            else:
                logger.error('第{}页 项目列表获取为空'.format(page_num))

            # 翻页
            for i in range(2, total_page_num + 1):
                yield scrapy.Request(
                    self.project_li_url_temp.format(i),
                )

    def parse_permit(self, response):
        """
        获取许可证详情
        :param response:
        :return:
        """
        item_eg = copy(response.meta['item_eg'])
        item_eg['permitId'] = response.xpath(
            "//td[contains(text(),'预售许可编号')]/following-sibling::td[1]/text()").extract_first()
        item_eg['districtName'] = response.xpath(
            "//td[contains(text(),'行政区')]/following-sibling::td[1]/text()").extract_first()
        item_eg['commencementDate'] = response.xpath(
            "//td[contains(text(),'开工日期')]/following-sibling::td[1]/text()").extract_first()
        item_eg['completionDate'] = response.xpath(
            "//td[contains(text(),'竣工日期')]/following-sibling::td[1]/text()").extract_first()
        item_eg['totalArea'] = response.xpath(
            "//td[contains(text(),'建筑面积')]/following-sibling::td[1]/text()").extract_first()
        item_eg['planningPermit'] = response.xpath(
            "//td[contains(text(),'工程规划许可证号')]/following-sibling::td[1]/text()").extract_first()
        item_eg['constructionPermit'] = response.xpath(
            "//td[contains(text(),'工程施工许可证号')]/following-sibling::td[1]/text()").extract_first()
        item_eg['preSaleDepositBank'] = response.xpath(
            "//td[contains(text(),'资金监管银行')]/following-sibling::td[1]/text()").extract_first()
        item_eg['preSaleAccountNum'] = response.xpath(
            "//td[contains(text(),'资金监管账号')]/following-sibling::td[1]/text()").extract_first()
        yield item_eg

    def parse_building_li(self, response):
        """
        获取楼栋列表
        :param response:
        :return:
        """
        item_eg = copy(response.meta['item_eg'])
        building_url = copy(response.meta['building_url'])
        try:
            resp = json.loads(response.body.decode())
            bd_li = resp['data']
            assert bd_li
        except:
            logger.error('{} {} 楼栋列表获取出错'.format(response.request.url, item_eg['projectName']))
        else:
            for bd_dict in bd_li:
                item_bd = FdcBuildingItem()
                item_bd['projectName'] = item_eg['projectName']
                item_bd['projectId'] = item_eg['projectId']
                item_bd['blockName'] = bd_dict.get('buildingName', None)
                item_bd['buildingId'] = bd_dict.get('uuid', None)
                item_bd['buildingNo'] = bd_dict.get('buildingNumber', None)
                yield item_bd

                # 获取当前楼栋的单元列表
                unit_li = bd_dict.get('unitList', list())
                if unit_li:
                    for unit_dict in unit_li:
                        unit_id = unit_dict.get('unitId', str(1)) if unit_dict.get('unitId', str(1)) else ''
                        headers = dict(Referer=urllib.parse.urljoin(response.request.url, building_url), )
                        data = dict(
                            buildUuid=item_bd['buildingId'],
                            unitId=unit_id,
                            id=item_eg['projectId'],
                        )
                        # 获取房号列表
                        yield scrapy.FormRequest(
                            self.rm_li_url,
                            formdata=data,
                            headers=headers,
                            callback=self.parse_room_li,
                            meta=dict(item_bd=deepcopy(item_bd), unit_id=unit_id, ),
                            priority=10,
                        )
                else:
                    logger.warning('{}  {}-{}-{} 楼栋单元列表为空'.format(response.request.url, item_bd['projectName'],
                                                                  item_bd['blockName'], item_bd['buildingId']))

    def parse_room_li(self, response):
        """
        获取房号列表
        :param response:
        :return:
        """
        item_bd = copy(response.meta['item_bd'])
        unit_id = copy(response.meta['unit_id'])
        try:
            resp = json.loads(response.body.decode())
            rm_li = resp['data']
            assert rm_li
        except:
            logger.error(
                '{}-{}-{} 房号列表获取为空'.format(item_bd['projectName'], item_bd['projectId'], item_bd['blockName'], ))
        else:
            for rm_dict in rm_li:
                item_rm = FdcRoomItem()
                item_rm['projectId'] = item_bd['projectId']
                item_rm['blockName'] = item_bd['blockName']
                item_rm['buildingId'] = item_bd['buildingId']
                item_rm['unitNo'] = unit_id if unit_id else None
                item_rm['roomId'] = rm_dict.get('houId', None)
                item_rm['roomFloor'] = rm_dict.get('floor', None)
                item_rm['roomNo'] = rm_dict.get('number', None)
                item_rm['saleStatus'] = rm_dict.get('status', None)
                item_rm['roomUse'] = rm_dict.get('houseUser', None)
                item_rm['innerArea'] = rm_dict.get('inArea', None)
                item_rm['apportionmentArea'] = rm_dict.get('outArea', None)
                item_rm['undecoratedPrice'] = rm_dict.get('decprice', None)
                item_rm['preSalePermit'] = rm_dict.get('licenseId', None)
                yield item_rm

    @staticmethod
    def _get_total_page_num(_str: str) -> int or None:
        """
        获取总页数
        :param _str: <str> or None
        :return: <int> or None
        """
        regex = re.compile(r'\d+')
        try:
            ret = int(regex.findall(_str)[0])
        except:
            return
        else:
            return ret

    @staticmethod
    def _get_regi_id(_str: str) -> int or None:
        """
        获取regiId
        :param _str: <str> or None
        :return: <int> or None
        """
        regex = re.compile(r'regiId=(.*?)&')
        try:
            ret = regex.findall(_str)[0]
        except:
            return
        else:
            return ret
